/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.foxinline.servico;

import br.com.foxinline.modelo.Configuracao;
import br.com.foxinline.modelo.Grupo;
import br.com.foxinline.modelo.Setor;
import br.com.foxinline.modelo.Usuario;
import java.security.Principal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.faces.context.FacesContext;
import javax.persistence.NoResultException;
import javax.persistence.NonUniqueResultException;
import javax.persistence.Query;

/**
 *
 * @author ely
 */
@Stateless
public class UsuarioServico extends ServicoGenerico<Usuario> {

    @EJB
    ConfiguracaoServico configuracaoServico;
    @EJB
    GrupoServico grupoServico;

    public UsuarioServico() {
        super(Usuario.class);
    }

    @Override
    public void salvar(Usuario entity) {
        salvar(entity, false);
    }

    public void salvar(Usuario usuario, boolean gerarToken) {
        Configuracao configuracao = configuracaoServico.find();

        if (gerarToken) {
            usuario.setToken(gerarToken());
        }

        if (configuracao.getProjetoTabularium()) {
            if (usuario.getGrupos() != null) {
                usuario.getGrupos().add(grupoServico.find("usuario_tabularium"));
            }
        }
        if (configuracao.getProjetoTabularium()) {
            if (usuario.getGrupos() != null) {
                usuario.getGrupos().add(grupoServico.find("usuario_tabulario"));
            }
        }

        super.salvar(usuario);
    }

    /**
     * Gera o token do usuário
     *
     * @param usuario
     */
    private String gerarToken() {
        Random rand = new Random();
        String token = Long.toHexString(rand.nextLong()) + Long.toHexString(rand.nextLong());

        return token;
    }

    public void atualizar(Usuario usuario, boolean removerToken) {
        if (removerToken) {
            usuario.setToken(null);
        }
        super.atualizar(usuario);
    }

    @Override
    public List<Usuario> pesquisarTodos() {
        String sql = "SELECT u FROM Usuario u WHERE u.id != 1";
        return getEntityManager().createQuery(sql).getResultList();
    }

    public boolean usuarioObrigatorio(Usuario usuario) {
        return !usuario.getNome().equals("");
    }

    public boolean emailObrigatorio(Usuario usuario) {
        return !usuario.getEmail().equals("");
    }

    public boolean senhaObrigatorio(Usuario usuario) {
        return !usuario.getSenha().equals("");
    }

    public boolean verificaSenha(String senha, Usuario usuario) {
        return usuario.getSenha().equals(senha);
    }

    public Usuario existLogin(String doc) {
        Usuario usuario;
        String sql = "Select u from Usuario u "
                + "where lower(u.login) like lower(:doc)";
        Query query = getEntityManager().createQuery(sql);
        query.setParameter("doc", doc);
        try {
            usuario = (Usuario) query.getResultList().get(0);

        } catch (NoResultException nr) {
            return null;
        } catch (NonUniqueResultException nre) {
            return null;
        } catch (Exception e) {
            return null;
        }

        return usuario;
    }

    /**
     *
     * @param senha
     * @param usuario
     * @return
     */
    public boolean verificaSenhaAntiga(String senha, Usuario usuario) {
        senha = Usuario.encryptPassword(senha);
        return senha.equals(usuario.getSenha());
    }

    public List<Usuario> pesquisarUsuario(Usuario usuario) {
        String sql = "SELECT u FROM Usuario u ";
        sql += " where ";
        if ((usuario.getNome() != null) && !usuario.getNome().equals("")) {
            sql += " lower(u.nome) like lower(:nome) and ";
        }
        if ((usuario.getLogin() != null) && !usuario.getLogin().equals("")) {
            sql += " lower(u.login) like lower(:login) and ";
        }
        sql += " 1=1 AND u.ativo = TRUE AND u.id != 1 Order by u.id ASC ";
//        System.err.print(sql);
        Query query = getEntityManager().createQuery(sql);

        if ((usuario.getNome() != null) && !usuario.getNome().equals("")) {
            query.setParameter("nome", "%" + usuario.getNome() + "%");
        }
        if ((usuario.getLogin() != null) && !usuario.getLogin().equals("")) {
            query.setParameter("login", usuario.getLogin());
        }
        return (List<Usuario>) query.getResultList();
    }

    public String getNomeUsuario(String usuario) {
        String sql = "SELECT u.nome FROM Usuario u ";
        sql += " where ";

        if ((usuario != null) && !usuario.equals("")) {
            sql += " lower(u.login) like lower(:login) and ";
        }
        sql += " u.ativo = TRUE";

        Query query = getEntityManager().createQuery(sql);

        if ((usuario != null) && !usuario.equals("")) {
            query.setParameter("login", usuario);
        }
        return (String) query.getSingleResult();
    }

    public Usuario verifySystemUserForLogin(String nome) {
        if (nome == null) {
            return null;
        }
        Usuario usr = null;
        try {
            final String sql = "select u from Usuario u where "
                    + "u.login like :nome";
            Query query = getEntityManager().createQuery(sql);
            query.setParameter("nome", nome);
            usr = (Usuario) query.getSingleResult();

        } catch (Exception e) {
            System.err.println("Nenhum usuário encontrado");
            return null;
        }
        return usr;
    }

    public Usuario getCurrentUser() {
        final Principal userPrincipal = FacesContext.getCurrentInstance().getExternalContext().getUserPrincipal();
        if (userPrincipal != null) {
            return verifySystemUserForLogin(userPrincipal.getName());
        }

        return null;
    }

    public List<Usuario> usuarioSetor(Setor setor) {
        String sql = "SELECT u FROM Usuario u JOIN u.setor s WHERE s.id = :id";
        Query query = getEntityManager().createQuery(sql);
        query.setParameter("id", setor.getId());
        return (List<Usuario>) query.getResultList();
    }

    public Usuario getUsuarioAtualViaToken(String token) {

        if (token == null) {
            Map<String, String> params = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
            token = params.get("create_password_token");
        }

        if (token != null || !token.trim().equals("")) {
            String sql = "SELECT u FROM Usuario u WHERE u.token like :token";

            Query query = getEntityManager().createQuery(sql);

            query.setParameter("token", token);

            return (Usuario) query.getSingleResult();
        }
        return new Usuario();
    }

    public String getNomeViaToken(String token) {
        try {
            if (token == null) {
                Map<String, String> params = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
                token = params.get("create_password_token");
            }
            System.err.println("nomeviatoken = " + token);
            System.err.println("token null = " + (token != null));
            System.err.println("token '' = " + (!token.trim().equals("")));
            System.err.println("token null || '' = " + (token != null || !token.trim().equals("")));

            if (token != null || !token.trim().equals("")) {
                String sql = "SELECT u FROM Usuario u WHERE u.token like :token";
                System.err.println("token sql = " + sql);

                Query query = getEntityManager().createQuery(sql);

                query.setParameter("token", token);


                return ((Usuario) query.getSingleResult()).getNome();
            }

        } catch (NoResultException nre) {
            return null;
        } catch (Exception e) {
            return null;
        }
        return "";
    }

    /**
     * Pesquisar por todos os usuários que não se encontram na lista passada por
     * parâmetro
     *
     * @param <b>usuarios</b> Lista de usuários que não devem ser retornados
     * @return <b>queryResult</b> lista de usuários que não existem na lista
     * enviada por parâmetro
     */
    public List<Usuario> notContainsIn(List<Usuario> usuarios) {
        String usuariosId = "";
        for (Usuario usuario : usuarios) {
            usuariosId += usuario.getId() + ",";
        }

        if (!usuariosId.isEmpty()) {
            usuariosId = usuariosId.substring(0, usuariosId.length() - 1);

            String sql = "select u from Usuario u where u.id not in (" + usuariosId + ") AND u.id != 1";
            Query query = getEntityManager().createQuery(sql);

            return query.getResultList();
        }

        return new ArrayList<Usuario>();
    }

    public boolean isAdmin() {

        Usuario usuario = getCurrentUser();

        return isAdminAuxiliar(usuario);
    }

    public boolean isAdmin(Usuario usuario) {
        return isAdminAuxiliar(usuario);
    }

    private boolean isAdminAuxiliar(Usuario usuario) {
        for (Grupo grupo : usuario.getGrupos()) {
            if (grupo.getNome().toLowerCase().contains("administrador")) {
                return true;
            }
        }
        return false;
    }

    public boolean isUsuarioProjeto(Usuario usuario) {
        if (isAdmin()) {
            return isAdmin();
        }

        if (usuario != null && usuario.getId() != null) {

            String sql = "SELECT p FROM Projeto p JOIN p.acompanhantes a "
                    + "WHERE a.id = :usuarioID";

            Query query = getEntityManager().createQuery(sql);
            query.setParameter("usuarioID", usuario.getId());

            if (query.getResultList() == null || query.getResultList().isEmpty()) {
                return false;
            }
            return true;
        }
        return false;
    }
}
